Skip to content

docs(i18n): compile the i18n README's 8 blocks and drop its ledger entry - #7988

Merged
baozhoutao merged 1 commit into
mainfrom
claude/issue-5174-ungated-docs-batch16
Sep 6, 2026
Merged

docs(i18n): compile the i18n README's 8 blocks and drop its ledger entry#7988
baozhoutao merged 1 commit into
mainfrom
claude/issue-5174-ungated-docs-batch16

Conversation

@claude

@claude claude Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Part of #5174 — batch 16 of the UNGATED_DOCS burn-down. The card stays open.

packages/i18n/README.md leaves the ledger: every ts/tsx fence in it now compiles --strict against the packages' built dist/*.d.ts, so its entry in scripts/check-doc-snippet-types.mjs is deleted. Removals only inside that object literal; nothing else in the gate file changed.

Ledger arithmetic

reading base 9de3141a0 branch 707d692
UNGATED_DOCS entries 22 21
covered documents 205 206
covered documents holding a ts/tsx block 103 104
covered blocks 653 661
blocks to compile 495 503
declared fragments 158 158
semantic failures 0 0
gate-file numstat 0 added, 2 deleted

Programmatic diff of the two UNGATED_DOCS literals, both imported and compared as objects: removed = ['packages/i18n/README.md'], added = [], reason-changed = [], key order preserved for all 21 survivors.

Fragments went 158 to 158: zero new FRAGMENT_MARKER declarations. All eight blocks earned coverage by compiling, not by being excused.

Strictness region unchanged. From the Fence scanning banner to EOF, sha256 f46b5662ba336f026bca3a0003e0b7979789d48d0291fa5760be7d23c8ed0160 on the base and the same value on the branch — 1178 lines on both sides, the banner moving 758 to 756 because the two-line entry above it is gone. Identical to the value batch 15 measured, as it should be with nothing landing in the region since.

The census that picked this document

Re-taken on this branch's own base with the gate's own exports, over all 22 entries minus the five that are off-limits (root README.md is not a packages/* README; packages/auth/README.md is held by draft PR #7685; packages/plugin-gantt/README.md and packages/plugin-kanban/README.md belong to PR #7985; packages/plugin-chatbot/README.md is deferred):

packages/i18n/README.md is the uniquely largest remaining debt at 8 blocks / 11 diagnostics — the next five candidates all sit at 7 blocks (plugin-detail 21 diagnostics, collaboration 18, permissions 18, types 6, layout 2). The fixed tie-break (larger measured debt first) never had to be applied: nothing ties it on block count.

What the 11 diagnostics were, and what was done about them

Seven TS2304 were fragment shape — three blocks that used I18nProvider, App, Preview and useObjectTranslation without ever importing or defining them. Each now carries the real import plus a declare const placeholder typed to the shipped surface, in the spelling packages/app-shell/README.md already uses.

The other four were real API drift, and they are the reason this page mattered. The formatting block documented a positional signature the package has never shipped:

  • formatDate(new Date(), 'en') — the second parameter is DateFormatOptions, so the locale is { locale: 'en' } (TS2559).
  • formatCurrency(99.99, 'USD', 'en') — takes (value, options?: CurrencyFormatOptions), two parameters, not three (TS2554).
  • formatNumber(1234567, 'de') — second parameter is NumberFormatOptions (TS2559).
  • formatRelativeTime(-3, 'days', 'en') — takes (date, locale?) and derives the unit from the distance to now; there is no unit parameter (TS2554).

A reader copying any of those four lines got code that did not compile. Each replacement was executed against the built package and its trailing comment is the string that actually came back: "Jan 1, 2025", "$99.99", "1.234.567", "3 days ago". The date example moved from new Date() to a fixed new Date(2025, 0, 1) so the documented output is reproducible rather than wrong on every day but one, and the prose above the block now states the calling convention: value first, options object second, with formatRelativeTime the one exception.

The useObjectTranslation block moved from a bare top-level destructure to the same call inside a component, so the page no longer shows a hook called outside a component while teaching the hook.

No packages/** source was touched, no public type widened, no lenient alias added, no gate loosened, and nothing was invented: every name the page now teaches is exported by @object-ui/i18n's built dist/index.d.ts.

Probes — six, each predicted in writing before it ran

Every leg proved its mutation on disk (occurrence counts of the injected and the deleted text, plus git hash-object against the HEAD blob) and proved its restore by an empty git diff HEAD; every script carried a trap ... EXIT INT TERM with absolute paths. No rebuild is owed on any leg: the gate reads the mutated bytes straight from the working tree, so no built artifact sits between a mutation and its reading.

probe predicted observed
P1 ablation of the ledger removal ALONE (README repaired, entry restored) exit 0, coverage silently falling back to 22 ungated / 653 blocks / 495 to compile exactly that — exit 0, 22 ungated, Covered blocks: 653 — 495 to compile, 495 of 495 judged, 0 failed. The entry is what suppresses the verification
P2 planted TS2339 (direction to directionTypo) in the repaired LanguageBar block exit 1, one TS2339, 503 of 503 judged, 1 failed exit 1, 503 of 503 judged, 1 failed, TS2339: Property 'directionTypo' does not exist on type .... Two diagnostics, not the one predicted: a consequential TS2304 on the now-undefined direction in the JSX below. Same direction, one more diagnostic than written down
P3 README reverted to base bytes, ledger removal kept exit 1 with the original 11 diagnostics exit 1, all 11, same codes and same sites: TS2304 x7, TS2559 x2, TS2554 x2, across 4 failed blocks
P4 the other reader's anchor — peer line ^18.0.0 to ^18.1.0 scripts/__tests__/doc-version-claims.test.ts red red on 3 assertions (the ratchet, the KNOWN_CLAIMS inventory, and the peer-line assertion against the manifest). Its control leg ran first and was green on the committed bytes, so the pin is non-vacuous
P5 the placeholders are load-bearing — declare const App: () => ReactNode retyped to number exit 1, a JSX element-type error exit 1, TS2604: JSX element type 'App' does not have any construct or call signatures and TS2786: 'App' cannot be used as a JSX component. The annotations are judged, not silently widened
P6 check:readme-exports judges import NAMES — I18nProvider to I18nProviderNope exit 1, 1 fabricated exit 1, 441 real, 0 wrong-path, 1 fabricated, naming the line. Its control leg was green at 442 real, 0 fabricated

Six of six in the predicted direction. The one deviation is P2's count, recorded above rather than smoothed over.

Gates, at 707d692

Exit codes captured by redirect-then-capture, never through a pipe; each row quotes the gate's own verdict line.

gate exit verdict line
pnpm check:doc-snippets 0 Scanned 227 document(s): 206 covered (104 of them hold a ts/tsx block), 21 ungated · 503 of 503 block(s) judged, 0 failed
pnpm check:doc-fences 0 every TypeScript block in 227 document(s) is fenced ts/tsx/typescript
pnpm check:readme-exports 0 442 of them self-imports judged (442 real, 0 wrong-path, 0 fabricated)
pnpm check:doc-types 0 Every documented component type is registered.
node scripts/check-doc-links.mjs 0 Links are valid across 17 scan roots.
pnpm check:doc-example-readers 0 OK 80 documented symbol(s), 3947 call site(s)
pnpm check:control-bytes 0 OK (scanned 6428 tracked text file(s); skipped 85 binary)
node scripts/check-node-esm-load.mjs 0 every workspace entry loads; the three ERR_UNKNOWN_FILE_EXTENSION lines are declared by design
pnpm type-check:scripts 0 tsc -p tsconfig.scripts.json, no diagnostics
node scripts/check-changeset-presence.mjs 0 2 file(s) changed, 0 of them published source of a package the release covers · no changeset is owed
node scripts/check-governed-queue-guard.mjs --test (both paths) 0 NOT GOVERNED — 2 path(s) checked against 5 governed surface(s); none matched

Tests — every file that reads either changed path, in one run: scripts/__tests__/ × 8 (check-doc-snippet-types, check-doc-component-types, check-doc-expression-carriage, check-doc-fence-languages, check-links-workflow, check-readme-exports, check-skill-examples, doc-version-claims), packages/types/src/__tests__/ × 4, packages/plugin-gantt/src/readme-navigation-example.test.ts, packages/react/src/__tests__/LazyPluginLoader.jsdocExample.test.ts, examples/schema-catalog/test/component-fixture-declared-keys.test.ts, and packages/app-shell/src/views/metadata-admin/ResourceEditPage.referencesErrorState.test.tsx16 files, 598 tests, all passing. The owning package: pnpm exec vitest run packages/i18n/62 files, 1031 tests passing — plus pnpm --filter @object-ui/i18n type-check exit 0.

Declared narrowing. turbo ls --affected against the base names 35 packages, which is package granularity reacting to a root-level script edit, not 35 readers: the only readers of either changed path are the 16 test files above. Those 35 suites are a declared narrowing to CI, not a skipped run. Lint here is turbo run lint per package, so the repository-wide sweep is CI's; the narrowed run over exactly this diff is eslint --no-inline-config --format json on both paths — 2 entries, 0 errors, and eslint's own answer for the README is File ignored because no matching configuration was supplied, so the real lint surface of this diff is the one .mjs file at 0 errors 0 warnings. eslint.config.js declares no project / projectService / parserOptions.project, so type-aware linting is off and this diff cannot move the verdict on any file it does not touch.

Readers of the changed document

reader what it reads
scripts/__tests__/doc-version-claims.test.ts the KNOWN_CLAIMS restatement row pinning the peer line `react` ^18.0.0 at line 23 against the package manifest. Lines 22–23 are byte-identical across this diff (sha256 of the two-line slice compared on both refs); P4 mutated the line and the pin went red on 3 assertions
packages/app-shell/src/views/metadata-admin/i18n.ts prose citation of the engine.* carve-out section (a header comment)
packages/app-shell/src/views/metadata-admin/metadata-form-i18n.ts the same carve-out, cited in a header comment
packages/app-shell/src/views/metadata-admin/ResourceEditPage.referencesErrorState.test.tsx the same carve-out, cited in a test comment
scripts/check-doc-snippet-types.mjs the gate itself, which now compiles the page instead of excusing it

The engine.* carve-out section those three cite is untouched by this diff — every hunk lands between lines 57 and 146 of the old file, all inside the API examples.

Concurrency

No other batch of this seat is in flight, so this is the sole removal on the UNGATED_DOCS literal right now — the base 9de3141a0 already carries batches 14 and 15 (LANDED notes 5557265479 and 5557366292). Of the 12 open pull requests at branch time, none touches packages/i18n/README.md or scripts/check-doc-snippet-types.mjs; file lists were read for all 12, including all 1048 paths of the release pull request #5400. Draft PR #7685 does touch packages/i18n/src/locales/*.ts (10 files) but neither of this branch's two paths, and the examples here are judged against the shipped types on origin/main, not against that branch.

🤖 Generated with Claude Code

https://claude.ai/code/session_01MM7kaS4dPpYHV5BsMyu4tQ


Generated by Claude Code

Every ts/tsx fence in packages/i18n/README.md now compiles --strict against
the built dist/*.d.ts, so its UNGATED_DOCS entry in
scripts/check-doc-snippet-types.mjs is removed (22 -> 21 entries; removals
only, nothing else in that file changed).

The 11 measured diagnostics decomposed into 7 TS2304 fragment-shape names and
4 real API drift. The formatting block documented a positional signature the
package has never shipped: formatDate/formatCurrency/formatNumber take an
options object second (DateFormatOptions / CurrencyFormatOptions /
NumberFormatOptions), and formatRelativeTime takes (date, locale) and derives
the unit itself -- so formatCurrency(99.99, 'USD', 'en') and
formatRelativeTime(-3, 'days', 'en') were both uncopyable as written. Every
replacement call was executed against the built package and its output comment
is the real string.

The three fragment blocks gain real imports plus `declare const` placeholders
typed to the shipped surface, matching the existing spelling in
packages/app-shell/README.md; the useObjectTranslation block now shows the
hook inside a component rather than at module top level. No packages/**
source is touched, no public type widened, no gate loosened, and no new
FRAGMENT_MARKER declared -- all 8 blocks earn coverage by compiling.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MM7kaS4dPpYHV5BsMyu4tQ
@github-actions

github-actions Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 50 chunks) 3185.9 KB 3191.4 KB
Main entry chunk (gzip) 143.5 KB 350 KB
Entry file index-8xzvN5SF.js
Status PASS

The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it.


📦 Bundle Size Report

Package Size Gzipped
app-shell (consoleActionDispatch.js) 0.20KB 0.19KB
app-shell (index.js) 15.67KB 5.75KB
app-shell (runtime-config.js) 20.68KB 7.36KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 10.06KB 3.86KB
auth (ActiveOrganizationStorage.js) 25.05KB 9.16KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 2.07KB 1.00KB
auth (AuthProvider.js) 40.18KB 10.59KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 18.15KB 5.39KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.65KB 2.22KB
auth (SocialSignInButtons.js) 9.61KB 3.89KB
auth (UserMenu.js) 3.41KB 1.23KB
auth (auth-gate-events.js) 1.29KB 0.66KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 40.21KB 10.80KB
auth (createAuthenticatedFetch.js) 8.46KB 3.43KB
auth (index.js) 3.19KB 1.44KB
auth (invitation-status.js) 1.22KB 0.70KB
auth (org-roles.js) 6.66KB 2.78KB
auth (phone-identifier.js) 1.11KB 0.66KB
auth (types.js) 0.59KB 0.35KB
auth (useAuth.js) 5.30KB 1.02KB
auth (useWorkspaceAdminStatus.js) 5.13KB 2.35KB
collaboration (CommentThread.js) 26.08KB 7.56KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.49KB 2.64KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (index.js) 1.68KB 0.73KB
collaboration (useCollaborationTranslation.js) 6.05KB 2.52KB
collaboration (useCommentSearch.js) 1.98KB 0.88KB
collaboration (useConflictResolution.js) 7.75KB 1.86KB
collaboration (useMentionNotifications.js) 1.81KB 0.68KB
collaboration (usePresence.js) 6.33KB 1.84KB
collaboration (useRealtimeSubscription.js) 7.91KB 2.01KB
components (index.js) 497.06KB 113.79KB
core (index.js) 6.96KB 2.79KB
create-plugin (index.js) 10.08KB 3.26KB
data-objectstack (index.js) 182.08KB 50.62KB
fields (index.js) 242.44KB 61.25KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
i18n (builtinAggregateLabels.js) 0.86KB 0.49KB
i18n (currency.js) 1.22KB 0.64KB
i18n (fallbackInterpolation.js) 6.25KB 2.77KB
i18n (i18n.js) 4.28KB 1.75KB
i18n (index.js) 3.65KB 1.47KB
i18n (pickLocalized.js) 7.62KB 3.26KB
i18n (provider.js) 26.89KB 9.04KB
i18n (useDisplayLocale.js) 2.85KB 1.45KB
i18n (useObjectLabel.js) 34.34KB 9.17KB
i18n (useSafeTranslation.js) 5.60KB 2.33KB
layout (index.js) 38.84KB 10.94KB
mobile (MobileProvider.js) 0.92KB 0.49KB
mobile (ResponsiveContainer.js) 0.94KB 0.38KB
mobile (breakpoints.js) 1.51KB 0.70KB
mobile (createOfflineDataSource.js) 5.61KB 1.75KB
mobile (index.js) 1.99KB 0.87KB
mobile (offlineQueue.js) 3.91KB 1.35KB
mobile (pwa.js) 0.97KB 0.49KB
mobile (serviceWorker.js) 1.48KB 0.62KB
mobile (serviceWorkerSource.js) 3.41KB 1.48KB
mobile (useBreakpoint.js) 1.54KB 0.65KB
mobile (useGesture.js) 6.96KB 1.98KB
mobile (useOfflineSync.js) 1.99KB 0.72KB
mobile (usePullToRefresh.js) 2.53KB 0.85KB
mobile (useResponsive.js) 0.72KB 0.42KB
mobile (useSpecGesture.js) 4.39KB 1.66KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 11.71KB 4.29KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 6.24KB 2.16KB
permissions (discardProofCache.js) 1.04KB 0.55KB
permissions (evaluator.js) 5.12KB 1.74KB
permissions (index.js) 0.93KB 0.41KB
permissions (store.js) 0.91KB 0.42KB
permissions (useFieldPermissions.js) 1.28KB 0.53KB
permissions (usePermissions.js) 4.83KB 2.27KB
plugin-ai (index.js) 15.16KB 3.68KB
plugin-calendar (index.js) 47.35KB 13.21KB
plugin-charts (index.js) 70.31KB 19.62KB
plugin-chatbot (index.js) 193.53KB 46.05KB
plugin-dashboard (index.js) 131.41KB 34.43KB
plugin-designer (index.js) 211.51KB 43.01KB
plugin-detail (index.js) 247.59KB 63.48KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 131.01KB 32.32KB
plugin-gantt (index.js) 167.16KB 40.99KB
plugin-grid (index.js) 208.56KB 56.63KB
plugin-kanban (index.js) 52.30KB 14.49KB
plugin-list (index.js) 113.24KB 27.66KB
plugin-map (index.js) 20.35KB 6.77KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 43.42KB 11.92KB
plugin-timeline (index.js) 29.95KB 8.67KB
plugin-tree (index.js) 9.16KB 3.18KB
plugin-view (index.js) 84.33KB 20.75KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.90KB 0.85KB
providers (UploadProvider.js) 11.66KB 3.50KB
providers (index.js) 0.45KB 0.23KB
providers (types.js) 0.01KB 0.04KB
react-runtime (index.js) 5.62KB 2.34KB
react (LazyPluginLoader.js) 4.47KB 1.63KB
react (SchemaRenderer.js) 81.07KB 26.86KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.63KB 2.18KB
react (schema-input.js) 2.32KB 1.24KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (codegen.js) 5.41KB 2.34KB
sdui-parser (dashboard-widget-options.js) 3.08KB 1.30KB
sdui-parser (index.js) 4.93KB 2.24KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (parse.js) 20.57KB 5.88KB
sdui-parser (provenance.js) 3.66KB 1.82KB
sdui-parser (types.js) 0.28KB 0.23KB
sdui-parser (validate.js) 10.35KB 3.60KB
types (ai.js) 0.20KB 0.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 2.87KB 1.00KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (complex.js) 2.74KB 1.41KB
types (crud.js) 0.20KB 0.18KB
types (dashboard-filter-alias.js) 6.23KB 2.74KB
types (data-display.js) 3.75KB 1.85KB
types (data-protocol.js) 0.20KB 0.19KB
types (data.js) 0.20KB 0.18KB
types (designer.js) 1.85KB 0.85KB
types (disclosure.js) 0.20KB 0.18KB
types (error-code.js) 1.54KB 0.88KB
types (expression.js) 0.20KB 0.18KB
types (feedback.js) 0.20KB 0.18KB
types (field-types.js) 0.20KB 0.18KB
types (form.js) 0.20KB 0.18KB
types (http-inflight.js) 8.87KB 3.73KB
types (http-retry.js) 4.32KB 2.02KB
types (icon-key-migration.js) 4.26KB 1.63KB
types (index.js) 4.74KB 2.25KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 4.73KB 2.28KB
types (navigation.js) 0.20KB 0.18KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 0.20KB 0.18KB
types (plugin-scope.js) 0.20KB 0.18KB
types (record-components.js) 0.20KB 0.19KB
types (record-semantics.js) 1.28KB 0.67KB
types (registry.js) 0.20KB 0.18KB
types (reports.js) 0.20KB 0.18KB
types (select-option.js) 0.20KB 0.19KB
types (spec-report.js) 5.05KB 1.93KB
types (spec-ui-namespace.js) 0.20KB 0.19KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 6.28KB 2.87KB
types (ui-action.js) 8.11KB 3.32KB
types (views.js) 0.20KB 0.18KB
types (widget.js) 0.20KB 0.18KB

Size Limits

  • ✅ Core packages should be < 50KB gzipped
  • ✅ Component packages should be < 100KB gzipped
  • ⚠️ Plugin packages should be < 150KB gzipped

Copy link
Copy Markdown
Contributor

Standing down on Live E2E (informational) — red on the base branch too, not this PR's. domain:devx @ objectui execution seat, PM session session_01MM7kaS4dPpYHV5BsMyu4tQ, R45, 2026-09-06T07:07Z. Same signature as main 9de3141a scheduled run 34017174769 (job 101442890465): the published backend boots without its auth core (objectstack#16186); consumer-side anchor #7990. This diff is one README and two ledger lines — no backend pin, no e2e/ path. No fix to port, no re-run spent. Every other check is green or still running; the flip and arming wait on those.


Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation package: i18n

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants